<!DOCTYPE html>
<html lang="zh-CN">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="./css/index.css">
  <title>函数基础</title>
</head>

<body>

  <div class="box"></div>

  <div class="clic">点我</div>

  <script src="./js/index.js"></script>

  <!-- 
        函数：function 一等公民  具有最高优先权
            1.JS函数定义： 一个能执行的有自己功能方法的集合体 ： 本质上也是一个对象；

            2.执行结果： 完成某种特定的功能；

            3.函数的类型：
                本质上函数也是对象 顶级原型继承于Object

                只不过它的构造器是Function

                继承关系:
                     函数 instanceof Function extends Object

            4.作用：使得大量重复的代，把特定的功能集合到一起
                能够得到封装 提高可读性和运行速度 提高效率；

            5.函数的声明：
                function 函数名(){...代码块}；
                function 函数名(形式参数){...代码块 返回值}；

            6.函数调用：
                函数名(实际参数)；

            7.如何使用一个函数：
                1.知道函数名；
                2.知道函数的参数；
                3.知道返回值是什么；

            8.函数的输入和输出：
                输入：
                    意义：让代码执行更加定制化；
                        在括号中传入参数 可传入若干个参数；
                    参数存在哪？
                        1.函数声明的位置；
                            接收的参数：形参；
                        2.函数执行的位置；
                            传入的参数：实参；
                    参数对不齐怎么办？
                        1.实参 > 形参：
                            忽略多余的参数；
                        2.实参 < 形参：
                            缺少的参数都是undefined；
            9.返回值：
                1.说返回值之前 先说说表达式：
                    只要能通过运算、执行得到某种值的表述 都是表达式；
                    let a = (1 + 2) - 3 * 4 / 6 = 1
                2.返回值：  
                    任何代码 / 表打死 都有返回值 不仅仅局限在函数里；
                    let a = console.log(123) // 123；
                    consonle.log(a) // undefined；
                    结果是123 但是返回的是undefined；
                3.为什么需要返回值？意义何在？
                    意义在于：告诉浏览器，代码执行完毕了！ 
                4.函数的返回值：
                    js是单线程脚本语言 如果当前的内容没有执行完毕 是不会继续执行的；
                    所以函数往往需要一个返回值 来告诉浏览器 该函数执行完毕 可以继续往下；

                    1.函数未自定义返回值的时候 默认返回undefined；
                        function foo(){};
                        foo(); // undefined；
                    2.如何定义返回值：
                        在函数内容使用 return 返回值；
                        function foo(){
                            return 'foo'
                            console.log(1) // 永远不会被执行
                        }
                        foo() // 'foo';
                        return 语句之后的代码就不会被执行了；

                    返回值让函数相当于一个加工厂：
                        三要素： 输入 加工 输出；
                    从而能够完成一些特定功能；
            10.函数表达式：
                函数类型的表达式 与函数声明不一样 一般都是匿名表达式；
                效果就是： 给匿名函数赋一个变量名 作为其引用；
                let foo1 = function () foo2 { ... }
                foo1(); ...
                foo2() // 报错！ 因为foo2这个变量不存在 并没有被声明出来！
                
            11.阅读代码小技巧：
                遇到函数就跳过 只要函数没执行 就不去读它；

            12.函数传参：
                把函数作为参数 传入到另一个函数里 即回调函数;
                func A( cb =  func () {} ){ cb() }

            13.函数的名字：
                func foo(){} foo.name // foo
                注意点：
                    函数表达式：
                        如果表达式有名字 函数名就是它；
                        如果是匿名函数 则函数名是变量名
                        let foo = func sb(){}
                        foo.name // sb
                        let foo = func (){}
                        foo.name // foo
            14.立执行函数：IIFE (立即执行的函数表达式) Immedialtely Invoked Function Expression
                声明的时候就执行了！
                
                ;(function (a){...})(a) 注意前面这个分号 最好加上
                不然括号会被解析为运算符 强行参与到前面代码的运算中 容易翻车；
                当然，要是写代码每一句后面都加上分号 那就不用担心这问题了；

                好处：
                    1.保证函数的私有性 调用完之后就无法再次调用；
                    2.节省空间开销：执行完就没用了 被垃圾回收机制回收 节省内存空间；
                    3.创造私有作用域 秘密花园...

                写法规范：
                    尽量使用分号来表示立执行函数；
                    其他符号：
                        + - ~ 都可以
                        甚至可以直接写：
                            + - ~func (){...}()
                        但是不建议使用，因为这些符号存在隐式类型转换的问题，会发生歧义；
                        可以使用 ~~ 取反的取反 又返回原位了
                        ~~(func (){})() 但是能用一个分号搞定的 为啥要多写个波浪号呢？
            15.ES6的新函数写法：
                箭头函数：
                    ES5：let foo = func(){}
                    等价于：
                    ES6：let foo = () => {}
                    执行效果与普通函数没区别！写法更简洁，方便！

                    箭头函数传参：
                        (x,y) => { return x + y }

                    特点：
                        如果参数只有一个 执行的操作只有一句，可直接省略括号
                        x => x**2

                        等价于：
                        (x) => { return x**x }
                    注意点：
                        箭头函数的this指向比较特别 指向window 而不是调用它的对象
                        不可以作为构造函数！

                        this永远指向它运行时所在的对象，对于箭头函数来说 这个环境就是window

            作业：
                使用简单函数实现一个简单聊天框的功能：
                    要求：
                        没要求 自行想象 实现消息发送函数即可；
    -->
</body>

</html>